package com.swak.algs.paxos;

import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import com.google.common.collect.Maps;
import com.swak.utils.Lists;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * Paxos 算法
 * 
 * @author 618lf
 */
@Getter
@Setter
@Accessors(chain = true)
public class Paxos {

	private static Paxos ME = new Paxos();

	public static Paxos me() {
		return ME;
	}

	/**
	 * 结束标注
	 */
	AtomicBoolean finish = new AtomicBoolean(false);

	/**
	 * 所有的议员
	 */
	private Map<Integer, Proposer> proposers = Maps.newHashMap();

	/**
	 * 所有的投票者
	 */
	private List<Acceptor> acceptors = Lists.newArrayList();

	private Paxos() {
	}

	private NetWork newNetWork() {
		NetWork netWork = new NetWork();
		netWork.setDaemon(false);
		netWork.start();
		return netWork;
	}

	public Proposer newProposer() {
		Proposer proposer = new Proposer(newNetWork());
		proposers.put(proposer.id, proposer);
		return proposer;
	}

	public void newAcceptor() {
		Acceptor acceptor = new Acceptor(newNetWork());
		acceptors.add(acceptor);
	}

	public boolean isMajority(int size) {
		return (acceptors.size() / 2 + 1) <= size;
	}

	public boolean isFinish() {
		return this.finish.get();
	}

	public void finish() {
		this.finish.compareAndSet(false, true);
	}
}
